home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / byte0787.arc / IWPAS.ARC / PICTURES.P < prev    next >
Encoding:
Text File  |  1987-04-28  |  14.3 KB  |  519 lines

  1. { PICTURES.P -- picture file routines                   }
  2.  
  3. { Copyright (c) 1987, Ciarcia's Circuit Cellar          }
  4. {    All Rights Reserved                                }
  5.  
  6. {-------------------------------------------------------}
  7. { Dump a segmented address with a message               }
  8.  
  9. PROCEDURE DumpAddr(msg : strtype;
  10.                    segment,offset : INTEGER);
  11.  
  12. BEGIN
  13.  Writeln(msg,IntToHex(segment),':',
  14.              IntToHex(offset));
  15. END;
  16.  
  17.  
  18. {-------------------------------------------------------}
  19. { Get file spec if not present                          }
  20.  
  21. FUNCTION GetFSpec(fn: strtype) : strtype;
  22.  
  23. BEGIN
  24.  IF Length(fn) = 0              { if no file spec given }
  25.   THEN BEGIN
  26.    Write('Picture file name: ');
  27.    Readln(fn);                  { get one               }
  28.   END;
  29.  
  30.  GetFSpec := fn;                { else use given spec   }
  31.  
  32. END;
  33.  
  34. {-------------------------------------------------------}
  35. { Present message, return boolean response              }
  36.  
  37. FUNCTION Askit(msg : strtype) : BOOLEAN;
  38.  
  39. VAR
  40.  resp      : STRING[5];
  41.  
  42. BEGIN
  43.  Write(msg,' ');                { present question      }
  44.  Readln(resp);                  { get some answer       }
  45.  
  46.  Askit := FALSE;
  47.  IF Length(resp) <> 0           { categorize response   }
  48.   THEN IF UpCase(resp[1]) = 'Y'
  49.         THEN Askit := TRUE;
  50.  
  51. END;
  52.  
  53. {-------------------------------------------------------}
  54. { Allocate and initialize the picture buffer            }
  55.  
  56. PROCEDURE PicSetup(VAR newpic : picptr);
  57.  
  58. VAR
  59.  pels      : pelrng;
  60.  lines     : linerng;
  61.  
  62. BEGIN
  63.  
  64.  IF newpic <> NIL               { discard if allocated  }
  65.   THEN Dispose(newpic);
  66.  
  67.  New(newpic);                   { allocate new array    }
  68.  
  69. END;
  70.  
  71.  
  72. {-------------------------------------------------------}
  73. { Get a picture from the transmitter                    }
  74. { The bit rate depends on which PC you're using...      }
  75. { An 8 MHz AT can handle 28.8 K bits/sec                }
  76. { Sets RTS and DTR to switch the relay box before       }
  77. {  taking the picture, restores normal display after    }
  78. { Some debugging statements are commented out... you    }
  79. {  may need them to get your system running             }
  80.  
  81. PROCEDURE GetPicture(pic : picptr;
  82.                      resol : BYTE);
  83.  
  84. VAR
  85.  picbyte   : BYTE;              { byte from transmitter }
  86.  bptr      : byteptr;           { fake pointer to pic   }
  87.  
  88. BEGIN
  89.  
  90.  Port[comMCR] := $03;           { PC <-> trans serial   }
  91.                                 { camera -> monitor     }
  92.  
  93.  Delay(200);                    { pause to stabilize    }
  94.  
  95. (*
  96.  Write('Waiting for key press...');
  97.  Readln;
  98. *)
  99.  
  100.  bptr := Ptr(Seg(pic^),Ofs(pic^)-1);  { preset for loop }
  101.  
  102. (*
  103.  Writeln('KeyPressed is: ',KeyPressed);
  104.  Writeln('port end is:   ',(Port[comdata]=fldend));
  105. *)
  106.  
  107.  SendByte(resol);               { specify resolution    }
  108.  SendByte(XON);                 { prompt transmitter    }
  109.  
  110.  REPEAT                         { for each line         }
  111.   bptr := Ptr(Seg(bptr^),Ofs(bptr^)+1);   { tick ptr    }
  112.   WHILE ((Port[comLSR] AND DataReady) = 0) AND
  113.         NOT KeyPressed DO;      { stall waiting         }
  114.   bptr^ := Port[comdata];       { snag the byte         }
  115.  UNTIL (bptr^ = fldend) OR KeyPressed;
  116.  
  117. (*
  118.  Writeln('KeyPressed is: ',KeyPressed);
  119.  Writeln('port end is:   ',(Port[comdata]=fldend));
  120.  Writeln('data end is:   ',(bptr^=fldend));
  121. *)
  122.  
  123.  Port[comMCR] := $00;           { PC <-> rec serial     }
  124.                                 { rec -> monitor        }
  125.  
  126. END;
  127.  
  128. {-------------------------------------------------------}
  129. { Save picture file on disk                             }
  130. { Uses the smallest number of blocks to fit the data    }
  131.  
  132. PROCEDURE SavePicture(filespec : strtype;
  133.                       pic : picptr);
  134. VAR
  135.  ndx       : subrng;            { index into word array }
  136.  rndx      : REAL;              {  real equivalent      }
  137.  nblocks   : INTEGER;           { number of disk blocks }
  138.  xfered    : INTEGER;           { number actually done  }
  139.  
  140.  pfile     : FILE;              { untyped file for I/O  }
  141.  
  142. BEGIN
  143.  
  144.  Writeln('Writing ',filespec);
  145.  Assign(pfile,filespec);
  146.  Rewrite(pfile);
  147.  
  148.  ndx := 0;                      { start with first word }
  149.  
  150.  Write('  Data length = ');
  151.  WHILE (ndx < maxbuffer) AND    { WHILE not end of pic  }
  152.        (Lo(pic^.words[ndx]) <> fldend) AND
  153.        (Hi(pic^.words[ndx]) <> fldend) DO
  154.    ndx := ndx + 1;
  155.  
  156.  ndx := ndx + 1;                { fix 0 origin          }
  157.  
  158.  rndx := 2.0 * ndx;             { allow >32K numbers... }
  159.  Write(rndx:6:0,' bytes, file length = ');
  160.  
  161.  nblocks := ndx DIV 64;         { 64 words = 128 bytes  }
  162.  
  163.  IF (ndx MOD 64) <> 0           { partial block?        }
  164.   THEN nblocks := nblocks + 1;
  165.  
  166.  rndx := 128.0 * nblocks;       { actual file size      }
  167.  Writeln(rndx:6:0,' bytes');
  168.  
  169.  BlockWrite(pfile,pic^.words[0],nblocks,xfered);
  170.  
  171.  IF xfered <> nblocks           { completed?            }
  172.   THEN BEGIN
  173.    Writeln('Problem writing the file, error code: ',
  174.             IOerror);
  175.    Writeln('  Blocks computed: ',nblocks);
  176.    Writeln('  Blocks written:  ',xfered);
  177.   END;
  178.  
  179. END;
  180.  
  181.  
  182. {-------------------------------------------------------}
  183. { Load picture file from disk                           }
  184.  
  185. PROCEDURE LoadPicture(filespec : strtype;
  186.                       pic : picptr);
  187.  
  188. BEGIN
  189.  
  190.  Writeln('Reading ',filespec);
  191.  Assign(picfile,filespec);
  192.  
  193.  {$I- turn off I/O checking                             }
  194.  Reset(picfile);
  195.  IOerror := IOresult;
  196.  {$I+ turn on  I/O checking again                       }
  197.  
  198.  IF IOresult <> 0
  199.   THEN BEGIN
  200.    Writeln('Problem reading the file, IO error: ',
  201.             IOerror);
  202.    HALT;
  203.   END;
  204.  
  205.  {$I- turn off I/O checking                             }
  206.  Read(picfile,pic^);            { this does the read    }
  207.  IOerror := IOresult;
  208.  {$I+ turn on  I/O checking again                       }
  209.  
  210.  IF NOT (IOresult IN [0,$99])   { $99 = short block, OK }
  211.   THEN BEGIN
  212.    Writeln('Problem reading the file, IO error: ',
  213.             IOerror);
  214.    HALT;
  215.   END;
  216.  
  217. END;
  218.  
  219.  
  220. {-------------------------------------------------------}
  221. { Send picture to display                               }
  222. { Sets RTS and DTR to switch the relay box to ensure    }
  223. {  a good connection                                    }
  224.  
  225. PROCEDURE SendPicture(pic : picptr);
  226.  
  227. VAR
  228.  bptr      : byteptr;           { fake pointer to pic   }
  229.  
  230. BEGIN
  231.  
  232.  Port[comMCR] := $00;           { PC <-> rec serial     }
  233.                                 { rec -> monitor        }
  234.  
  235.  Delay(100);                    { pause to stabilize    }
  236.  
  237.  bptr := Ptr(Seg(pic^),Ofs(pic^)-1);  { set byte ptr    }
  238.  
  239.  REPEAT                         { for each line         }
  240.   bptr := Ptr(Seg(bptr^),Ofs(bptr^)+1);   { tick ptr    }
  241.   WHILE (Port[comdata] = XOFF) AND NOT KeyPressed DO;
  242.   WHILE ((Port[comLSR] AND THRE) = 0) AND
  243.         NOT KeyPressed DO;      { stall for data        }
  244.   Port[comdata] := bptr^;       { send the byte         }
  245.  UNTIL (bptr^ = fldend) OR KeyPressed;
  246.  
  247. END;
  248.  
  249.  
  250. {-------------------------------------------------------}
  251. { Set up frame and line syncs in a buffer               }
  252. { This should be done only in freshly allocated buffers }
  253.  
  254. PROCEDURE SetSyncs(pic1 : picptr);
  255.  
  256. VAR
  257.  lndx      : linerng;           { index into lines      }
  258.  
  259. BEGIN
  260.  
  261.  pic1^.fmt.syncF := fieldsync;  { set up empty picture  }
  262.  
  263.  FOR lndx := 0 TO maxline DO BEGIN
  264.   pic1^.fmt.lines[lndx].syncL := linesync;
  265.   FillChar(pic1^.fmt.lines[lndx].pels[0],maxpel+1,0);
  266.  END;
  267.  
  268.  pic1^.fmt.syncE := fldend;     { set ending control    }
  269.  
  270. END;
  271.  
  272.  
  273. {-------------------------------------------------------}
  274. { Decompress pic1 into pic2                             }
  275.  
  276. PROCEDURE Expand(pic1,pic2 : picptr);
  277.  
  278. CONST
  279.  errthresh = 10;           { max errors in frame        }
  280.  
  281. VAR
  282.  bptr      : ^byte;
  283.  lndx      : linerng;
  284.  pndx      : pelrng;
  285.  overflow  : BOOLEAN;
  286.  oldbyte   : BYTE;
  287.  reps      : INTEGER;
  288.  frametop  : BOOLEAN;
  289.  giveup    : BOOLEAN;
  290.  errcount  : INTEGER;
  291.  
  292. BEGIN
  293.  
  294.  bptr := Ptr(Seg(pic1^),Ofs(pic1^));
  295.  
  296.  SetSyncs(pic2);                { fill in the syncs     }
  297.  
  298.  lndx := 0;
  299.  pndx := 0;
  300.  
  301.  frametop := TRUE;
  302.  giveup := FALSE;
  303.  errcount := 0;
  304.  WHILE (bptr^ <> fldend) AND NOT giveup
  305.  DO BEGIN { and now the data...   }
  306.   CASE bptr^ OF
  307.    fieldsync : BEGIN
  308.             IF (lndx <> 0) OR (pndx <> 0)
  309.              THEN BEGIN
  310.               Writeln('Field sync found after data');
  311.              END;
  312.             oldbyte := 0;
  313.             frametop := TRUE;
  314. (*          Writeln('Field sync'); *)
  315.            END;
  316.    linesync : BEGIN
  317.             IF (lndx < maxline) AND NOT frametop
  318.              THEN lndx := lndx + 1
  319.              ELSE frametop := false;
  320.             oldbyte := 0;
  321.             pndx := 0;
  322.             overflow := FALSE;
  323. (*          Write('.'); *)
  324.            END;
  325.    fldend : BEGIN               { can't get here...     }
  326.              Writeln;
  327.              Writeln('Surprise at having found field end!');
  328.             END;
  329.    ELSE BEGIN
  330.     CASE (bptr^ AND $F0) OF
  331.      $00..$3F : BEGIN
  332.               pic2^.fmt.lines[lndx].pels[pndx] := bptr^;
  333.               oldbyte := bptr^;
  334.               IF pndx < maxpel
  335.                THEN BEGIN
  336.                 pndx := pndx + 1;
  337.                 IF overflow
  338.                  THEN BEGIN
  339.                   Write('Too much data on line ',lndx:3);
  340.                   Writeln('  pel data ',ByteToHex(bptr^));
  341.                   errcount := Succ(errcount);
  342.                  END;
  343.                END
  344.                ELSE BEGIN
  345.                 pndx := 0;
  346.                 overflow := TRUE;
  347.                END;
  348. (*            Writeln('Data: ',ByteToHex(bptr^)); *)
  349.              END;
  350.      rep1  : BEGIN
  351.               FOR reps := 1 TO (bptr^ AND $0F) DO BEGIN
  352.                pic2^.fmt.lines[lndx].pels[pndx] := oldbyte;
  353.                IF pndx < maxpel
  354.                 THEN BEGIN
  355.                  pndx := pndx + 1;
  356.                  IF overflow
  357.                   THEN BEGIN
  358.                    Write('Too much data on line ',lndx:3);
  359.                    Writeln('   1x rep ',ByteToHex(bptr^));
  360.                    errcount := Succ(errcount);
  361. (*                 pndx := 0; *)
  362.                   END
  363.                 END
  364.                 ELSE BEGIN
  365.                  pndx := 0;
  366.                  overflow := TRUE;
  367.                 END;
  368. (*             Writeln('Rep1: ',ByteToHex(bptr^)); *)
  369.               END;
  370.              END;
  371.      rep16 : BEGIN
  372.               FOR reps := 1 TO (16 * (bptr^ AND $0F)) DO BEGIN
  373.                pic2^.fmt.lines[lndx].pels[pndx] := oldbyte;
  374.                IF pndx < maxpel
  375.                 THEN BEGIN
  376.                  pndx := pndx + 1;
  377.                  IF overflow
  378.                   THEN BEGIN
  379.                    Write('Too much data on line ',lndx:3);
  380.                    Writeln('  16x rep ',ByteToHex(bptr^));
  381.                    errcount := Succ(errcount);
  382. (*                 pndx := 0; *)
  383.                   END
  384.                 END
  385.                 ELSE BEGIN
  386.                  pndx := 0;
  387.                  overflow := TRUE;
  388.                 END;
  389. (*             Writeln('Rep16: ',ByteToHex(bptr^)); *)
  390.               END;
  391.              END;
  392.      ELSE BEGIN
  393.       Writeln('Garbage byte: ',ByteToHex(bptr^),
  394.                   ' at line ',lndx,' pel ',pndx);
  395.       errcount := Succ(errcount);
  396.      END;
  397.     END;
  398.    END;
  399.   END;
  400.   IF errcount > errthresh
  401.    THEN giveup := TRUE;
  402.   bptr := Ptr(Seg(bptr^),Ofs(bptr^)+1);  { next input byte }
  403.  END;
  404.  
  405.  IF giveup
  406.   THEN BEGIN
  407.    Writeln('Too many errors -- giving up!');
  408.    HALT;
  409.   END;
  410.  
  411. (* Writeln; *)
  412.  
  413. END;
  414.  
  415.  
  416. {-------------------------------------------------------}
  417. { Drop current count into picture                       }
  418. { Ticks pointer by the number of bytes added in         }
  419.  
  420. PROCEDURE DoCount(reps : INTEGER;
  421.                   VAR bptr : byteptr);
  422.  
  423. BEGIN
  424.  
  425.  IF reps >= 256
  426.   THEN BEGIN
  427.    bptr^ := rep16;              { default = 256         }
  428.    bptr := Ptr(Seg(bptr^),Ofs(bptr^)+1);
  429.    reps := reps - 256;          { fix the remainder     }
  430.   END;
  431.  
  432.  
  433.  IF (reps AND $F0) <> 0
  434.   THEN BEGIN
  435.    bptr^ := rep16 + (reps SHR 4);
  436.    bptr := Ptr(Seg(bptr^),Ofs(bptr^)+1);
  437.    reps := reps AND $0F;
  438.   END;
  439.  
  440.  IF reps <> 0
  441.   THEN BEGIN
  442.    bptr^ := rep1 + reps;
  443.    bptr := Ptr(Seg(bptr^),Ofs(bptr^)+1);
  444.   END;
  445.  
  446. END;
  447.  
  448.  
  449. {-------------------------------------------------------}
  450. { Compress pic1 into pic2                               }
  451.  
  452. PROCEDURE Compress(pic1,pic2 : picptr);
  453.  
  454. VAR
  455.  bptr      : ^byte;
  456.  lndx      : linerng;
  457.  pndx      : pelrng;
  458.  oldbyte   : BYTE;
  459.  reps      : INTEGER;
  460.  
  461. BEGIN
  462.  
  463. {--- fill buffer with zeros to ensure no trash          }
  464.  
  465.  FillChar(pic2^.words[0],maxbuffer,0);
  466.  FillChar(pic2^.words[maxbuffer DIV 2],maxbuffer,0);
  467.  
  468.  bptr := Ptr(Seg(pic2^),Ofs(pic2^));
  469.  
  470.  bptr^ := fieldsync;            { flag the start        }
  471.  bptr := Ptr(Seg(bptr^),Ofs(bptr^)+1);
  472.  
  473.  FOR lndx := 0 TO maxline DO BEGIN
  474.   bptr^ := linesync;            { flag new line         }
  475.   bptr := Ptr(Seg(bptr^),Ofs(bptr^)+1);
  476.   oldbyte := 0;
  477.   reps := 0;                    { force leading zero    }
  478.  
  479.   FOR pndx := 0 TO maxpel DO BEGIN
  480.    IF pic1^.fmt.lines[lndx].pels[pndx] = oldbyte
  481.     THEN reps := reps + 1       { accumulate count      }
  482.     ELSE BEGIN                  { new byte, send ...    }
  483.      IF reps > 1
  484.       THEN DoCount(reps,bptr);  { n reps, send count    }
  485.      IF reps = 1                { 1 rep, copy old byte  }
  486.       THEN BEGIN
  487.        bptr^ := oldbyte;
  488.        bptr := Ptr(Seg(bptr^),Ofs(bptr^)+1); { step ptr }
  489.       END;
  490.  
  491.      bptr^ := pic1^.fmt.lines[lndx].pels[pndx]; { new   }
  492.      bptr := Ptr(Seg(bptr^),Ofs(bptr^)+1);   { step ptr }
  493.      reps := 0;                 { reset counter         }
  494.      oldbyte := pic1^.fmt.lines[lndx].pels[pndx];
  495.     END;
  496.   END;
  497.  
  498. {--- send last count and trailing zero                  }
  499.  
  500.   IF reps > 1
  501.    THEN DoCount(reps,bptr);     { n reps, send count    }
  502.   IF reps = 1                   { 1 rep, copy old byte  }
  503.    THEN BEGIN
  504.     bptr^ := oldbyte;
  505.     bptr := Ptr(Seg(bptr^),Ofs(bptr^)+1);    { step ptr }
  506.    END;
  507.  
  508.   bptr^ := 0;                   { force trailer zero    }
  509.  
  510. (*Write('.'); *)
  511.  
  512.  END;
  513.  
  514.  bptr^ := fldend;               { flag the ending       }
  515.  Writeln;
  516.  
  517. END;
  518.  
  519.